package com.ssd.demo.base.util;

import io.searchbox.client.JestClient;
import io.searchbox.client.JestClientFactory;
import io.searchbox.client.JestResult;
import io.searchbox.client.config.HttpClientConfig;
import io.searchbox.core.Bulk;
import io.searchbox.core.Bulk.Builder;
import io.searchbox.core.Delete;
import io.searchbox.core.Get;
import io.searchbox.core.Index;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import io.searchbox.indices.DeleteIndex;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ssd.demo.base.core.BaseEntity;
import com.ssd.demo.base.exception.ESException;

public class ECUtil {

	private static JestClient client;
	static {
		JestClientFactory factory = new JestClientFactory();
		factory.setHttpClientConfig(new HttpClientConfig.Builder("http://localhost:9200").multiThreaded(true).build());
		client = factory.getObject();
	}

	public static <T extends BaseEntity> void insert(T t, String indexname, String mappingname) {
		ECUtil.insert(t, indexname, mappingname, new ECIDGet<T>() {
			@Override
			public String getId(T t) {
				return t.getId().toString();
			}
		});
	}

	/**
	 * 单条插入
	 * 
	 * @param t
	 * @param indexname
	 *            索引名称
	 * @param mappingname
	 * @param ecIDGet
	 *            ec的id获取
	 */
	public static <T> void insert(T t, String indexname, String mappingname, ECIDGet<T> ecIDGet) {
		try {
			Index index = new Index.Builder(JSON.toJSONString(t)).id(ecIDGet.getId(t)).index(indexname)
					.type(mappingname).build();
			client.execute(index);
		} catch (IOException e) {
			throw new ESException("插入es异常", e);
		}
	}

	/**
	 * 批量插入
	 * 
	 * @param t
	 * @param indexname
	 * @param mappingname
	 */
	public static <T extends BaseEntity> void batchInsert(List<T> list, String indexname, String mappingname) {
		ECUtil.batchInsert(list, indexname, mappingname, new ECIDGet<T>() {
			@Override
			public String getId(T t) {
				return t.getId().toString();
			}
		});
	}

	/**
	 * 批量插入
	 * 
	 * @param t
	 * @param indexname
	 * @param mappingname
	 * @param ecIDGet
	 *            not null
	 */
	public static <T extends BaseEntity> void batchInsert(List<T> list, String indexname, String mappingname,
			ECIDGet<T> ecIDGet) {
		try {
			Builder builder = new Bulk.Builder().defaultIndex(indexname).defaultType(mappingname);
			for (T t : list) {
				builder.addAction(new Index.Builder(JSON.toJSONString(t)).id(ecIDGet.getId(t)).build());
			}
			client.execute(builder.build());
		} catch (IOException e) {
			throw new ESException("批量插入es异常", e);
		}
	}

	public static <T> T getByDocId(Class<T> clazz, String docId, String indexname, String mappingname) {

		try {
			Get get = new Get.Builder(indexname, docId).type(mappingname).build();
			JestResult result = client.execute(get);
			
			return JSON.parseObject(result.getSourceAsString(), clazz);
		} catch (IOException e) {
			throw new ESException(Log.format("es获取单条数据异常 docId {} class {}", docId, clazz), e);
		}
	}

	/**
	 * 删除数据
	 * 
	 * @param docId
	 * @param indexname
	 * @param mappingname
	 */
	public static void deleteDocById(String docId, String indexname, String mappingname) {
		try {
			client.execute(new Delete.Builder(docId).index(indexname).type(mappingname).build());
		} catch (Exception e) {
			throw new ESException(Log.format("es删除数据异常 docId {} ", docId), e);
		}
	}

	/**
	 * 删除索引
	 * 
	 * @param indexname
	 */
	public static void deleteIndex(String indexname) {
		try {
			client.execute(new DeleteIndex.Builder(indexname).build());
		} catch (IOException e) {
			throw new ESException(Log.format("es删除索引异常 indexname {} ", indexname), e);
		}
	}

	public static <T> List<T> getList(Class<T> clazz, ESQueryParam param, String indexname, String mappingname) {

		try {
			Search search = new Search.Builder(param.toString()).addIndex(indexname).addType(mappingname).build();
			SearchResult sr = client.execute(search);

			if (sr.getTotal() != 0) {
				JSONObject json = (JSONObject) JSON.parse(sr.getJsonString());
				JSONArray jsons = json.getJSONObject("hits").getJSONArray("hits");
				List<T> list = new ArrayList<T>(sr.getTotal());

				for (Object o : jsons) {
					JSONObject jo = (JSONObject) o;
					JSONObject _source = jo.getJSONObject("_source");
					list.add(JSON.toJavaObject(_source, clazz));
				}

				return list;
			}

		} catch (IOException e) {
			throw new ESException("es查询出错 ", e);
		}
		return null;
	}

	/**
	 * 获取ecId的抽象
	 * 
	 * @author xiaoruihu
	 * @param <T>
	 */
	public static interface ECIDGet<T> {
		public String getId(T t);
	}

}
